#!/usr/bin/env python
"""
Showgrid.py
Graphically represent a processor grid.

Renderer
-r gnuplot: Not yet implemented
-r vtk: VTK toolkit (DEFAULT)
-r graphviz: Direct graphviz output (with -Tpdf option). Good for testing purposes for example

Options:
-h/--help: this help
-o, --output: output filename prefix for non-interactive output)
-2, --2D: 2D Graphviz. With VTK, produces a flat 3D representation, suitable for some kind of topologies
-3, --3D: 3d Graphviz (DEFAULT)
-p, --pdf: pdf output
--png: png output (Internet format)
--vrml: VRML 2.0 (VRML97) output (VTK only)
--obj: OBJ Wavefront file format. VTK only 
-w, --weights(VTK): display weights link and processor weights (DEFAULT=OFF)
-s, --space arg: space between nodes in Graphviz algorithm (DEFAULT=5)  
-d, --debug: Print debug messages (DEFAULT=OFF)
--rsphere: sphere radius (DEFAULT=15)

Usage: ./showgrid.py [-r renderer] [--rsphere radius spheres] [-s, --space length of
edges] [-2 2D representation] [-3 3D] [-d/--debug debug flag]
[-o/--output output file] [-w print weights] [-h this help] <vmap file>

Examples:

With Graphviz
./showgrid.py -r graphviz -2 --png ./vmaps/vmap_triangle.out

With VTK
./showgrid.py -3 -w --vrml ./vmaps/vmap_triangle.out 


Basile Clout, November 2007
"""

import os
import sys
import string
import getopt
import pprint
from datetime import *
from string import Template
import re

import vtk
from math import sqrt

def pvmap3D(fpos):
    """ parse a 3D dot file
    """

    nodes={}
    edges=[]
    
    pnode = re.compile(r'\s*(\w+) \[z="?(-?\d+)"?, label="(\w+) \((\d+\.?\d*)\)", pos="(\d+),(\d+)".*$')
    pedge = re.compile(r'\s*(\w+) -> (\w+) \[label="(\d+\.?\d*)\\n(\d+\.?\d*)", .*$')
    
    for line in fpos:
        mnode = pnode.match(line)
        medge = pedge.match(line)
        if mnode:
            l = mnode.groups()
            nodes[l[0]] = [ l[2], float(l[3]), [int(l[1]), int(l[4]), int(l[5])] ]
        elif medge:
            l = medge.groups()
            edges.append([l[0], l[1], [float(l[2]), float(l[3])]])
            
    return nodes, edges


def pvmap2D(fpos):
    """ parse a 3D dot file
    """

    nodes={}
    edges=[]
    
    pnode = re.compile(r'\s*(\w+) \[label="(\w+) \((\d+\.?\d*)\)", pos="(\d+),(\d+)".*$')
    pedge = re.compile(r'\s*(\w+) -> (\w+) \[label="(\d+\.?\d*)\\n(\d+\.?\d*)", .*$')
    
    for line in fpos:
        mnode = pnode.match(line)
        medge = pedge.match(line)
        if mnode:
            l = mnode.groups()
            nodes[l[0]] = [ l[1], float(l[2]), [int(l[3]), int(l[4]), 0] ]
        elif medge:
            l = medge.groups()
            edges.append([l[0], l[1], [float(l[2]), float(l[3])]])
            
    return nodes, edges


def vtk_clusters(clusters, nodes):
    """
    Create a semi-transparent sphere for each cluster
    """

    actors = []
    
    for c in clusters:
        x, y, z, i = 0.0, 0.0, 0.0, 0
        maxl, gap = 0, 80
    
        if len(c)>1:
            # Get barycenter
            for n in c:
                x += nodes[n][2][0]
                y += nodes[n][2][1]
                z += nodes[n][2][2]
                i += 1

            x, y, z = x/i, y/i, z/i
            
            for n in c:
                l = sqrt((x-nodes[n][2][0])**2 + (y-nodes[n][2][1])**2 + (z-nodes[n][2][2])**2)
                if l>maxl:
                    maxl=l

        else:
            x, y, z = nodes[c[0]][2][0], nodes[c[0]][2][1], nodes[c[0]][2][2],
            gap *= 1.5
            
        sphere = vtk.vtkSphereSource()
        sphere.SetThetaResolution(32)
        sphere.SetPhiResolution(64)
        sphere.SetRadius(maxl+gap)

        sphereMap = vtk.vtkPolyDataMapper()
        sphereMap.SetInputConnection(sphere.GetOutputPort())

        sphereActor = vtk.vtkActor()
        sphereActor.SetMapper(sphereMap)
        sphereActor.GetProperty().SetSpecularColor(0,1,0)
        sphereActor.GetProperty().SetOpacity(0.15)
        sphereActor.SetPosition(x,y,z)

        actors.append(sphereActor)

    return actors
                                  

            
def vtk_label_node(node, rsphere):
    """ Insert the 3D label corresponding to node
    """

    myvector = [0, 0, 0.2]              # Orientation of the text
    myfactor = 5                      # Deepness of the text
    myscale = [10, 10, 10]           # Scale relatively to the scene

    text = vtk.vtkVectorText()
    text.SetText(node[0])
    mycaption = str(node[1])
    
    caption1 = vtk.vtkCaptionActor2D()
    caption1.GetPositionCoordinate().SetCoordinateSystemToWorld()
    caption1.GetPositionCoordinate().SetValue(-rsphere/2, -rsphere/2, -rsphere/2)
    caption1.SetWidth(0.08)
    caption1.SetHeight(0.04)
    caption1.BorderOff()
    caption1.ThreeDimensionalLeaderOn()
    caption1.SetAttachmentPoint(node[2])
    caption1.SetCaption(node[0])
    caption1.GetCaptionTextProperty().SetFontSize(10)

    caption2 = vtk.vtkCaptionActor2D()
    caption2.GetPositionCoordinate().SetCoordinateSystemToWorld()
    caption2.GetPositionCoordinate().SetValue(-20, -20, -20)
    caption2.SetWidth(0.2)
    caption2.SetHeight(0.032)
    caption2.BorderOff()
    caption2.GetCaptionTextProperty().SetFontFamilyToCourier()
    caption2.GetCaptionTextProperty().ItalicOff()
    caption2.GetCaptionTextProperty().SetColor(0,1,0)
    caption2.GetCaptionTextProperty().ShadowOff()
    caption2.ThreeDimensionalLeaderOn()
    caption2.SetAttachmentPoint(node[2])
    caption2.SetCaption(mycaption)
    caption2.GetCaptionTextProperty().SetFontSize(10)

    return caption1, caption2


def vtk_label_edge(edge, nodes, mytype):
    """ Insert the 3D label corresponding the edge (tube)
    
    type = 0 if bandwidth label
    type = 1 if latency
    """

    node1 = nodes[edge[0]]
    node2 = nodes[edge[1]]
    
    if mytype == 0:
        mycaption = str(edge[2][0])

    elif mytype == 1:
        mycaption = str(edge[2][1])

    attachment = [node1[2][0]+(node2[2][0]-node1[2][0])/2-10, node1[2][1]+(node2[2][1]-node1[2][1])/2-10, node1[2][2]+(node2[2][2]-node1[2][2])/2-10]
    
    caption = vtk.vtkCaptionActor2D()
    caption.GetPositionCoordinate().SetCoordinateSystemToWorld()
    caption.GetPositionCoordinate().SetValue(0, 0, 0)
    caption.SetWidth(0.2)
    caption.SetHeight(0.032)
    caption.BorderOff()
    caption.GetCaptionTextProperty().SetFontFamilyToCourier()
#    caption.GetCaptionTextProperty().SetJustificationToCentered()
    caption.GetCaptionTextProperty().ItalicOff()
    caption.GetCaptionTextProperty().SetColor(1,1,0)
    caption.GetCaptionTextProperty().ShadowOff()
    caption.ThreeDimensionalLeaderOn()
    caption.SetAttachmentPoint(attachment)
    caption.SetCaption(mycaption)
    caption.GetCaptionTextProperty().SetFontSize(10)
    return caption


def renderVTK(_nodes, _edges, clusters, rsphere, _rfactor, filename, weights, type):
    """ VTK rendering
    """
        
    wx, wy = 1200, 700
#    wx, wy = 600, 300
    rtube = rsphere/5
    rfactor = _rfactor
    minbdw, maxbdw, minlat, maxlat, mincpu, maxcpu = 100000000, 0, 10000000, 0, 10000000, 0
    miny, maxx = 1000000, 0
    labels = []
    blabels, llabels = [], []
    myedges = []
    legend = 1
    backcolor = [0, 0, 0]               # Black background
    titlecolor = [1, 1, 1]              # White titles
    

    # LUT tables

    # Lut nodes
    lut0 = vtk.vtkLookupTable()
    lut0.SetHueRange(0, 0)
    lut0.SetSaturationRange(1, 1)
    lut0.SetValueRange(0.2, 1)
    lut0.SetNumberOfColors(256)
    lut0.Build()

    # lut bandwidth
    lut = vtk.vtkLookupTable()
    lut.SetHueRange(0, 0.16)
    lut.SetNumberOfColors(256)
    lut.Build()

    # lut latency
    lut2 = vtk.vtkLookupTable()    
    lut2.SetHueRange(0.5, 0.66)
    lut2.SetNumberOfColors(256)
    lut2.Build()
   
#    ren = vtk.vtkRenderer()
#    ren2 = vtk.vtkRenderer()
   
##     for node in _nodes.itervalues():

##         myradius = rsphere*node[1]
        
##         sphere = vtk.vtkSphereSource()
##         sphere.SetThetaResolution(16)
##         sphere.SetPhiResolution(32)
##         sphere.SetRadius(myradius)
        
##         sphereMap = vtk.vtkPolyDataMapper()
##         sphereMap.SetInputConnection(sphere.GetOutputPort())
        
##         sphereActor = vtk.vtkActor()
##         sphereActor.SetMapper(sphereMap)
##         sphereActor.GetProperty().SetSpecularColor(0,1,0)
##         sphereActor.SetPosition(node[2])

##         ren.AddActor(sphereActor)
##         ren2.AddActor(sphereActor)

    nodes = vtk.vtkPoints()
    nodes.SetDataTypeToFloat()
    nodesColor = vtk.vtkFloatArray()
    nodesCell = vtk.vtkCellArray()
    
    i=0
    for node in _nodes.itervalues():
        myid = nodes.InsertPoint(i, node[2])

        nodesColor.InsertNextValue(node[1])
        if node[1]<mincpu:
            mincpu=node[1]
        if node[1]>maxcpu:
            maxcpu=node[1]

        nodesCell.InsertNextCell(1)
        nodesCell.InsertCellPoint(i)

        i+=1

        if node[2][0] > maxx:
            maxx = node[2][0]
        if node[2][1] < miny:
            miny = node[2][1]

        mylabel, mycaption = vtk_label_node(node, rsphere)       # Create the node label
        labels.append(mylabel)
        labels.append(mycaption)

    # Add two legend nodes
    
#    if legend == 1:

#        nodeleg1 = [maxx+2*rsphere, miny-4*rsphere, 0]
#        nodeleg2 = [maxx+2*rsphere, miny-2*rsphere, 0]

##         nodelegmin = vtk.vtkPoints()
##         nodelegmin.SetDataTypeToFloat()
##         nodelegminColor = vtk.vtkFloatArray()
##         nodelegminCell = vtk.vtkCellArray()
                
##         myid = nodelegmin.InsertPoint(0, nodeleg1)
##         nodelegminColor.InsertNextValue(mincpu/2)
##         nodelegminCell.InsertNextCell(1)
##         nodelegminCell.InsertCellPoint(0)
    
##         myid = nodelegmin.InsertPoint(0, nodeleg2)
##         nodelegminColor.InsertNextValue(maxcpu/2)
##         nodelegminCell.InsertNextCell(1)
##         nodelegminCell.InsertCellPoint(0)

##         nodesLegPolyMin = vtk.vtkPolyData()
##         nodesLegPolyMin.SetPoints(nodelegmin)
##         nodesLegPolyMin.GetPointData().SetScalars(nodelegminColor)

 #       s1 = vtk.vtkSphereSource()
 #       s1.SetThetaResolution(16)
 #       s1.SetPhiResolution(32)
 #       s1.SetRadius(rsphere)
        
        
## #        ss = vtk.vtkSphereSource()
##         sphereleg = vtk.vtkLegendBoxActor()
##         sphereleg.SetNumberOfEntries(2)
##         sphereleg.SetEntry(0, s1.GetOutput(), "my node min", [1.0, 0, 0])
##         sphereleg.SetEntry(1, s1.GetOutput(), "my node max", [1.0, 1.0, 0])
##         sphereleg.ScalarVisibilityOn()
##         sphereleg.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay()
##         sphereleg.GetPositionCoordinate().SetValue(0.4, 0.1)
##         sphereleg.SetHeight(0.1)
##         sphereleg.SetWidth(0.5)
##         #        sphereleg.GetEntryTextProperty().SetFontSize(int(wy*0.05))
##         print "#entries = ",sphereleg.GetNumberOfEntries()

        
    nodesPoly = vtk.vtkPolyData()
    nodesPoly.SetPoints(nodes)
    nodesPoly.GetPointData().SetScalars(nodesColor)

    sphere = vtk.vtkSphereSource()
    sphere.SetThetaResolution(16)
    sphere.SetPhiResolution(32)
    sphere.SetRadius(rsphere)

    spheres = vtk.vtkGlyph3D()
    spheres.SetInput(nodesPoly)

    nbnodes = len(_nodes.keys())
    
    for i in range(0, nbnodes):
        spheres.SetSource(i, sphere.GetOutput())
    spheres.SetColorModeToColorByScalar()
#    spheres.SetScaleModeToDataScalingOff()
    spheres.SetIndexModeToScalar()
    spheres.SetRange(mincpu, maxcpu)

    spheresMap = vtk.vtkPolyDataMapper()
    spheresMap.SetInputConnection(spheres.GetOutputPort())
    spheresMap.SetLookupTable(lut0)
    spheresMap.SetScalarRange(mincpu, maxcpu)

    spheresActor = vtk.vtkActor()
    spheresActor.SetMapper(spheresMap)
    spheresActor.GetProperty().SetSpecularColor(0,1,0)
    spheresActor.GetProperty().SetOpacity(1)
    
    #Edges
    edgeBdwRadii = vtk.vtkFloatArray()
    edgeBdwArray = vtk.vtkCellArray()
    edgeBdw = vtk.vtkPoints()
    edgeBdw.SetDataTypeToFloat()

    edgeLatRadii = vtk.vtkFloatArray()

    for edge in _edges:

        # Print each edge only one time (present two times internally)
        if ((edge[0], edge[1]) not in myedges) and ((edge[1], edge[0]) not in myedges):
            myedges.append((edge[0], edge[1]))
        else:
            continue
        
        pt1 = edgeBdw.InsertNextPoint(_nodes[edge[0]][2])
        pt2 = edgeBdw.InsertNextPoint(_nodes[edge[1]][2])
        
        edgeBdwRadii.InsertNextValue(edge[2][0])
        edgeBdwRadii.InsertNextValue(edge[2][0])
        if edge[2][0]<minbdw:
            minbdw = edge[2][0]
        if edge[2][0] > maxbdw:
            maxbdw = edge[2][0]
        
        edgeLatRadii.InsertNextValue(edge[2][1])
        edgeLatRadii.InsertNextValue(edge[2][1])
        if edge[2][1]<minlat:
            minlat = edge[2][1]
        if edge[2][1] > maxlat:
            maxlat = edge[2][1]
        
        edgeBdwArray.InsertNextCell(2)
        edgeBdwArray.InsertCellPoint(pt1)
        edgeBdwArray.InsertCellPoint(pt2)

        blabel = vtk_label_edge(edge, _nodes, 0)
        llabel = vtk_label_edge(edge, _nodes, 1)
        blabels.append(blabel)
        llabels.append(llabel)

#    print "%f %f %f %f" % (minlat, maxlat, minbdw, maxbdw)
    
    edgeBdwPolyData = vtk.vtkPolyData()
    edgeBdwPolyData.SetPoints(edgeBdw)
    edgeBdwPolyData.SetLines(edgeBdwArray)
    edgeBdwPolyData.GetPointData().SetScalars(edgeBdwRadii)

    edgeLatPolyData = vtk.vtkPolyData()
    edgeLatPolyData.SetPoints(edgeBdw)
    edgeLatPolyData.SetLines(edgeBdwArray)
    edgeLatPolyData.GetPointData().SetScalars(edgeLatRadii)
    
    tubes = vtk.vtkTubeFilter()
    tubes.SetInput(edgeBdwPolyData)
    tubes.Update()
    tubes.SetNumberOfSides(12)
    tubes.SetRadius(rtube)
    tubes.SetRadiusFactor(rfactor)
    tubes.SetVaryRadiusToVaryRadiusByScalar()
    tubes.CappingOn()
    tubes.SetGenerateTCoordsToOff()

    tubes2 = vtk.vtkTubeFilter()
    tubes2.SetInput(edgeLatPolyData)
    tubes2.Update()
    tubes2.SetNumberOfSides(12)
    tubes2.SetRadius(rtube)
    tubes2.SetRadiusFactor(rfactor)
    tubes2.SetVaryRadiusToVaryRadiusByScalar()
    tubes2.CappingOn()
    tubes2.SetGenerateTCoordsToOff()

    tubesMap = vtk.vtkPolyDataMapper()
    tubesMap.SetInputConnection(tubes.GetOutputPort())
    tubesMap.SetScalarRange(minbdw, maxbdw)
    tubesMap.SetLookupTable(lut)
    tubesMap.Update()
    tubesMap.ScalarVisibilityOn()

    tubesMap2 = vtk.vtkPolyDataMapper()
    tubesMap2.SetInputConnection(tubes2.GetOutputPort())
    tubesMap2.SetScalarRange(minlat, maxlat)
    tubesMap2.SetLookupTable(lut2)
    tubesMap2.ScalarVisibilityOn()

    tubesActor = vtk.vtkActor()
    tubesActor.SetMapper(tubesMap)
    tubesActor.GetProperty().SetInterpolationToGouraud()

    tubesActor2 = vtk.vtkActor()
    tubesActor2.SetMapper(tubesMap2)
    tubesActor2.GetProperty().SetInterpolationToGouraud()

    # Text
    textBdw = vtk.vtkTextActor()
    textBdw.SetInput("Processor and Bandwidth weights")
    tprops = textBdw.GetTextProperty()
    tprops.SetColor(titlecolor)
    tprops.SetFontSize(10)
    tprops.ShadowOn()
    textBdw.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay()
    textBdw.GetPositionCoordinate().SetValue(0.1, 0.95)
    textBdw.SetWidth(0.7)
    textBdw.SetHeight(0.5)
    textBdw.ScaledTextOn()
    
    textLat = vtk.vtkTextActor()
    textLat.SetInput("Processor and Latency weights")
    tprops = textLat.GetTextProperty()
    tprops.SetColor(titlecolor)
    tprops.SetFontSize(10)
    tprops.ShadowOn()
    textLat.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay()
    textLat.GetPositionCoordinate().SetValue(0.6, 0.95)
    textLat.SetWidth(0.7)
    textBdw.SetHeight(0.5)
    textLat.ScaledTextOn()

    cluster_actors = vtk_clusters(clusters, _nodes)

    ren = vtk.vtkRenderer()
    ren2 = vtk.vtkRenderer()

    mycam = vtk.vtkCamera()
    
    ren.AddActor(tubesActor)
    ren.AddActor(spheresActor)
    ren.AddActor2D(textBdw)
    if weights == 1:
        for label in labels:
            ren.AddActor(label)
        for label in blabels:
            ren.AddActor(label)
    for cluster in cluster_actors:
        ren.AddActor(cluster)
    ren.SetViewport(0.0, 0.0, 0.5, 1.0) # SetViewport: (xmin, ymin, xmax, ymax)
    ren.SetBackground(backcolor)
    ren.SetActiveCamera(mycam)
        
    ren2.AddActor(spheresActor)
    ren2.AddActor(tubesActor2)
    ren2.AddActor2D(textLat)
    if weights == 1:
        for label in labels:
            ren2.AddActor(label)
        for label in llabels:
            ren2.AddActor(label)
    for cluster in cluster_actors:
        ren2.AddActor(cluster)
    ren2.SetViewport(0.5, 0.0, 1.0, 1.0)
    ren2.SetBackground(backcolor)
    ren2.SetActiveCamera(ren.GetActiveCamera())
    ren2.ResetCamera()

    
    renwin = vtk.vtkRenderWindow()
    renwin.AddRenderer(ren)
    renwin.AddRenderer(ren2)
    renwin.SetSize(wx,wy)

    if type == "png":
        print "Starting png file generation"
        ren.SetBackground(0.5,0.5,0.5)
        ren2.SetBackground(0.5, 0.5, 0.5)
        renwin.Render()
        w2i = vtk.vtkWindowToImageFilter()
        w2i.SetInput(renwin)
        writer = vtk.vtkPNGWriter()
        writer.SetInput(w2i.GetOutput())
        writer.SetFileName(filename+".png")
        writer.Write()
        print "%s.png successfully written." % filename

    elif type == "pdf":                   # 2D normal pdf (no 3d PDF for now...)
        print "Starting normal pdf file generation ..."
        renwin.Render()
        exp = vtk.vtkGL2PSExporter()
        exp.SetRenderWindow(renwin)
        exp.SetFileFormatToPDF()
        #exp.CompressOff()
        #exp.PS3ShadingOff()
        exp.SetFilePrefix(filename)
        exp.Write()
        print filename + ".pdf written!"

    elif type == "vrml":                # vrml file
        print "Starting VRML files generation ..."

#        ren.TwoSidedLightingOn()
#        ren2.TwoSidedLightingOn()
#        ren2.AutomaticLightCreationOff()

        renwin1 = vtk.vtkRenderWindow()
        renwin1.AddRenderer(ren)
        writer = vtk.vtkVRMLExporter()
        writer.SetRenderWindow(renwin1)
        writer.SetFileName(filename + "_bdw.wrl")
        writer.Write()
        print filename + "_bdw.wrl written!"

        renwin2 = vtk.vtkRenderWindow()
        renwin2.AddRenderer(ren2)
        writer2 = vtk.vtkVRMLExporter()
        writer2.SetRenderWindow(renwin2)
        writer2.SetFileName(filename + "_lat.wrl")
        writer2.Write()
        print filename + "_lat.wrl written!"

    elif type == "obj":                # obj (Wavefront) file
        print "Starting OBJ files generation ..."
        renwin1 = vtk.vtkRenderWindow()
        renwin1.AddRenderer(ren)
        writer = vtk.vtkOBJExporter()
        writer.SetRenderWindow(renwin1)
        writer.SetFilePrefix(filename+"_bdw")
        writer.Write()
        print filename + "_bdw.obj written!"
        renwin2 = vtk.vtkRenderWindow()
        renwin2.AddRenderer(ren2)
        writer = vtk.vtkOBJExporter()
        writer.SetRenderWindow(renwin2)
        writer.SetFilePrefix(filename+"_lat")
        writer.Write()
        print filename + "_lat.obj written!"
    else:
        renwin.Render()
        iren = vtk.vtkRenderWindowInteractor()
        iren.SetRenderWindow(renwin)
        
        style = vtk.vtkInteractorStyleTrackballCamera()
        iren.SetInteractorStyle(style)
        iren.Initialize()
        
        iren.Start()
        
    
def delDoubleEdges(_edges):
    """ Delete the edges in double
    """

    edges = []
    mv = 0

    for e in _edges:
        mv = 0
        for e1 in edges:
            if ((e[0], e[1]) == (e1[0], e1[1])) or ((e[1], e[0])==(e1[0], e1[1])):
                mv = 1
        if mv==0:
            edges.append(e)
                
    return edges


def getClusters(nodes, edges):
    """ Create the clusters coordinates
    """

    clusters = []
    used = []
    c = []

    
    # Build the clusters
    for n in nodes:

        if n in used:
            continue

        c = [n]
        used.append(n)
        for e in edges:
            if n in (e[0], e[1]):
                if n==e[0]:
                    de = e[1]
                else:
                    de = e[0]

                for e1 in edges:
                    if de in (e1[0], e1[1]):
                        if de==e1[0]:
                            pe = e1[1]
                        else:
                            pe = e1[0]

                        for e2 in edges:
                            if pe in (e2[0], e2[1]):
                                if pe==e2[0]:
                                    le = e2[1]
                                else:
                                    le = e2[0]
                                
                                if le == n and de not in c:
                                    c.append(de)
                                    used.append(de)

        clusters.append(c)
        
    return clusters

    

def main():
    """ Main function
    """

    vmap2dot = "/Users/basileclout/Desktop/repo/vmap2dot.pl"

    renderer = "vtk"                    # renderer may be 'vtk' or 'gnuplot'
    rsphere = 15                       # Base diameter of a sphere

    ifile = ""
    fl_debug = 0
    space = 5
    dim = 3
    weights = 0
    fn = "vmaptest"
    type = ""                           # Can be "pdf", "png", "vrml" or "obj
    
    try:
        opts, arg = getopt.getopt(sys.argv[1:], "do:r:hs:23wp", ["interactive","pdf", "vrml", "png", "obj","weights", "2D", "3D", "help", "debug", "rsphere=", "output=","renderer=", "space="])
    except getopt.error, msg:
        print msg
        print "For help, use --help"
        sys.exit(2)

    for o, a in opts:
        if o in ("-h", "--help"):
            print __doc__
            sys.exit(0)
        elif o in ("-o", "--output"):
            fn = a
        elif o in ("-2", "--2D"):
            dim = 2
        elif o in ("-p", "--pdf"):
            type = "pdf"
        elif o == "--interactive":
            type = ""
        elif o == "--png":
            type = "png"
        elif o == "--vrml":
            type = "vrml"
        elif o == "--obj":
            type = "obj"
        elif o in ("-3", "--3D"):
            dim = 3
        elif o in ("-w", "--weights"):
            weights = 1
        elif o in ("-s", "--space"):
            space = int(a)
        elif o in("-d", "--debug"):
            fl_debug = 1
        elif o == "--rsphere":
            rsphere = float(a)
        elif o in ("-r", "--renderer"):
            if a in ("gnuplot", "vtk", "graphviz"):
                renderer = a
            else:
                print "Renderer %s unknown (must be gnuplot, vtk or graphviz)! Use vtk." % a
        else:
            print "Option %s ignored!" % o


    if len(arg) != 1:
        print "Please enter a map file"
        sys.exit(2)
    else:
        ifile = arg[0]
        

    prefix = ifile.rsplit('.', 1)[0]

    if fn == "":
        fn = prefix
        
    tmpdot = prefix+".dot"
    tmppos = prefix+".pos"

    dot3Dline = "neato -Gmodel=circuit -Nshape=circle -Nz="" -Gdim=3 -Elen=%d -Gnormalize=true -o %s %s" % (space, tmppos, tmpdot)
    dot2Dline = "neato -Gmodel=circuit -Nshape=circle -Elen=%d -Gnormalize=true -o %s %s" % (space, tmppos, tmpdot)
    

    # Get the positions of the nodes
    order = "%s %s > %s;\n" % (vmap2dot, ifile, tmpdot)

    # VTK
    if renderer in ('vtk', 'graphviz'):
        if dim == 3:
            order += "%s;\n" % dot3Dline
        elif dim == 2:
            order += "%s;\n" % dot2Dline
        os.system(order)

    else:
        print "Sorry, gnuplot renderering not yet implemented!"
        sys.exit(1)
    
    #Direct with Graphviz
    if renderer == "graphviz":
        if type in ("vrml", "obj"):
            print "No 3D format %s for 2D graphviz output!" % type
            sys.exit(1)
        order = "neato -Tpdf %s > %s" % (tmppos, fn+".pdf")
        os.system(order)
        
        if type == "pdf":
            print "%s successfully created." % (fn+".pdf")
        elif type == "png":
            order2 = "convert %s %s" % (fn+".pdf", fn+".png")
            os.system(order2)
            print "%s successfully created." % (fn+".png")
        sys.exit(0)

    
    try:
        fpos = file(tmppos, "r")
    except IOError:
        print "Impossible to open temp file %s" % tmppos
        sys.exit(2)

    if renderer == 'vtk':
        if dim == 3:
            nodes, _edges = pvmap3D(fpos)
        elif dim == 2:
            nodes, _edges = pvmap2D(fpos)
    else:
        print 'Not yet gnuplot!!'
        sys.exit(2)

    edges = delDoubleEdges(_edges)
    clusters = getClusters(nodes, edges)

    if fl_debug == 1:
        print "Nodes:"
        pprint.pprint(nodes)
        print "Edges:"
        pprint.pprint(edges)
        print "Clusters:"
        pprint.pprint(clusters)

    if renderer == 'vtk':
        renderVTK(nodes, edges, clusters, rsphere, space-1, fn, weights, type)


if __name__ == '__main__':
    main()
    
                
                
    
